package com.ysw.config;

import com.ysw.constant.ICodeStatus;
import com.ysw.constant.ServiceCodeStatus;
import com.ysw.dto.ResponseResult;
import com.ysw.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageConversionException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolationException;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @ClassName GlobalExceptionHandler
 * @Description 全局异常处理器
 * @Author ysw
 * @Date 2022/5/12 18:50
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
    /**
     * 处理指定异常
     *
     * @param request
     * @param exception
     * @return
     */
    @ResponseStatus(code = HttpStatus.BAD_REQUEST)
    @ExceptionHandler(value = {
            HttpMessageConversionException.class,
            MethodArgumentNotValidException.class,
            ConstraintViolationException.class})
    public ResponseResult handleBindException(HttpServletRequest request, Exception exception) {
        if (exception instanceof HttpMessageConversionException) {
            return ResponseResult.fail(ServiceCodeStatus.BAD_REQUEST);
        }
        /**
         * 对于validation 校验错误的异常信息进处理
         */
        else if (exception instanceof MethodArgumentNotValidException) {
            MethodArgumentNotValidException argumentNotValidException = (MethodArgumentNotValidException) exception;
            List<FieldError> fieldErrors = argumentNotValidException.getFieldErrors();
            Map<String, String> filedErrorInfo = fieldErrors.stream().collect(Collectors.toMap(FieldError::getField, FieldError::getDefaultMessage,(a,b)->a));
            return ResponseResult.fail(ServiceCodeStatus.BAD_REQUEST,filedErrorInfo);
        }
        /**
         * 表单单个参数做校验时候异常处理
         */
        else if (exception instanceof ConstraintViolationException) {
            ConstraintViolationException constraintViolationException = (ConstraintViolationException) exception;
            String message = constraintViolationException.getMessage();
            return ResponseResult.fail(ServiceCodeStatus.BAD_REQUEST.getCode(), message);
        }
        return ResponseResult.fail(exception.getMessage());
    }

    @ExceptionHandler
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ResponseResult handleException(HttpServletRequest request,Exception e){
        log.error("error:{}",e.getMessage());
        return ResponseResult.fail(ServiceCodeStatus.ERROR);
    }

    /**
     * 处理业务异常
     *
     * @param request
     * @param exception
     * @return
     */
    @ExceptionHandler(value = {ServiceException.class})
    public ResponseResult handleServiceException(HttpServletRequest request, Exception exception) {
        ServiceException serviceException = (ServiceException) exception;
        return ResponseResult.fail(serviceException.getCodeStatus());
    }
}